﻿using System;
using System.Windows;
using System.ComponentModel;
using System.Windows.Threading;
using OSVDB_TrayApp.Properties;
using OSVDB_Logic;
using System.Collections.Generic;
using OSVDB_Model;
using System.Windows.Data;
using System.Collections.ObjectModel;
using System.Windows.Input;
using System.Windows.Controls;
using System.Windows.Forms;
using System.Timers;
using System.Threading;


namespace OSVDB_TrayApp
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    /// 
    public partial class Window1 : Window
    {
        bool user_shutdown;
        Settings MySettings;
        System.Windows.Forms.Timer timer;
        bool firstStart;
        bool firstStartMil;
        bool firstStartPackAdv;
        bool firstStartPackExp;
        bool firstStartSecFoc;

        private NotifyBox box;

        public NotifyBox Box
        {
            get { return this.box; }
        }      

        public Window1()
        {
            firstStart = true;
            firstStartMil = true;
            firstStartPackAdv = true;
            firstStartPackExp = true;
            firstStartSecFoc = true;
            this.WindowStartupLocation = WindowStartupLocation.CenterScreen;
            MySettings = Settings.Default;
            box = new NotifyBox(this);
            this.box.OpeningMilliseconds = 500;
            this.box.StayOpenMilliseconds = 3000;
            this.box.HidingMilliseconds = 500;

            //Properties.Resources.Culture = MySettings.DefaultCulture;

            timer = new System.Windows.Forms.Timer();

            InitializeComponent();

            user_shutdown = false;

            this.box.Show();

            InitializeTimer();

            if (MySettings.getWatchList)
            {
                this.tab_WatchList.Visibility = Visibility.Visible;
            }
            else
            {
                this.tab_WatchList.Visibility = Visibility.Collapsed;
            }

            WaitCallback myCallback = new WaitCallback(afunction);

            //add this to the thread pool / queue a task 

            ThreadPool.QueueUserWorkItem(myCallback); 



            //LoadFeeds();
        }

        public void afunction(object o)
        {
            this.LoadFeeds();
            // do what ever the function is supposed to do. 
        } 


        public void InitializeTimer()
        {
            if (timer.Enabled)
            {
                timer.Stop();
            }

            int interval = this.MySettings.RefreshInterval * 60 * 1000;

            timer.Interval = interval;

            //timer.AutoReset = true;

            //timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
            timer.Tick += new EventHandler(timer_Elapsed);

            timer.Start();
            
        }

        void timer_Elapsed(object sender, EventArgs e)
        {
            WaitCallback myCallback = new WaitCallback(afunction);

            //add this to the thread pool / queue a task 

            ThreadPool.QueueUserWorkItem(myCallback); 

            InitializeTimer();
        }


        OSVDBVuln_BL vuln_bl;
        Collection<AbstractVuln> vulns;
        Milw0rm_BL milw;
        Collection<AbstractVuln> mil_vulns;
        SecFoc_BL sec;
        Collection<AbstractVuln> sec_vulns;
        PacketStormADV_BL packAdv;
        Collection<AbstractVuln> pacAdv_vulns;
        PacketStormEXP_BL packExp;
        Collection<AbstractVuln> pacExp_vulns;

        private delegate void UICallerDelegate();

        public void LoadFeeds()
        {
            //this.Cursor = System.Windows.Input.Cursors.Wait;
            
            vuln_bl = new OSVDBVuln_BL(MySettings.ApiKey, MySettings.OSVDBUrl);
            vulns = vuln_bl.getAll();

            if (MySettings.GetMilw0rm)
            {
                milw = new Milw0rm_BL(MySettings.Milw0rmURL);
                mil_vulns = milw.getAll();
            }

            if (MySettings.getSecFocus)
            {
                sec = new SecFoc_BL(MySettings.SecFocURL);
                sec_vulns = sec.getAll();

            }

            if (MySettings.getPacketVulns)
            {
                packAdv = new PacketStormADV_BL(MySettings.PacketADVURL);
                pacAdv_vulns = packAdv.getAll();
            }

            if (MySettings.getPacketExpl)
            {
                packExp = new PacketStormEXP_BL(MySettings.PacketExplURL);
                pacExp_vulns = packExp.getAll();
            }
            //this.Cursor = System.Windows.Input.Cursors.Arrow;

            UICallerDelegate dlg = new UICallerDelegate(setUI);
            //BeginInvoke(dlg, null);
            //dlg.BeginInvoke(dlg, null);
            Dispatcher.BeginInvoke(DispatcherPriority.Normal, dlg);
        }

        private void setUI()
        {
            this.LastUpdate.Content = "Updating...";

            this.ListOSVDBVulns.DataContext = vulns;

            this.ListOSVDBVulns.AddHandler(System.Windows.Controls.Control.MouseDoubleClickEvent, new RoutedEventHandler(HandleDoubleClick));

            if (this.CheckForNewEntries(vulns, "OSVDB"))
            {
                this.box.NotifyContent.Clear();

                this.box.NotifyContent.Add(new NotifyObject("There have been new entries at OSVDB", "OSVDB"));

                this.box.Notify();
            }
            if (MySettings.GetMilw0rm)
            {
                this.ListMilw0rm.DataContext = mil_vulns;
                this.tab_Milworm.Visibility = Visibility.Visible;

                this.ListMilw0rm.AddHandler(System.Windows.Controls.Control.MouseDoubleClickEvent, new RoutedEventHandler(HandleDoubleClick));

                if (this.CheckForNewEntries(mil_vulns, "Milw0rm"))
                {
                    this.box.NotifyContent.Clear();
                    this.box.NotifyContent.Add(new NotifyObject("There have been new entries at Milw0rm", "Milw0rm"));

                    this.box.Notify();
                }
            }
            else
            {
                this.tab_Milworm.Visibility = Visibility.Collapsed;
            }
            if (MySettings.getSecFocus)
            {
                this.ListSecFoc.DataContext = sec_vulns;
                this.tab_SecFoc.Visibility = Visibility.Visible;

                this.ListSecFoc.AddHandler(System.Windows.Controls.Control.MouseDoubleClickEvent, new RoutedEventHandler(HandleDoubleClick));

                if (this.CheckForNewEntries(sec_vulns, "SecFoc"))
                {
                    this.box.NotifyContent.Clear();

                    this.box.NotifyContent.Add(new NotifyObject("There have been new entries at Security Focus", "Security Focus"));

                    this.box.Notify();
                }
            }
            else
            {
                this.tab_SecFoc.Visibility = Visibility.Collapsed;
            }
            if (MySettings.getPacketVulns)
            {
                this.ListPacketStormADV.DataContext = pacAdv_vulns;
                this.tab_PacketStormADV.Visibility = Visibility.Visible;

                this.ListPacketStormADV.AddHandler(System.Windows.Controls.Control.MouseDoubleClickEvent, new RoutedEventHandler(HandleDoubleClick));

                if (this.CheckForNewEntries(pacAdv_vulns, "pacAdv"))
                {
                    this.box.NotifyContent.Clear();

                    this.box.NotifyContent.Add(new NotifyObject("There have been new entries at Packet Storm Advisories", "Packet Storm Advisories"));

                    this.box.Notify();
                }
            }
            else
            {
                this.tab_PacketStormADV.Visibility = Visibility.Collapsed;
            }
            if (MySettings.getPacketExpl)
            {
                this.ListPacketStormEXP.DataContext = pacExp_vulns;
                this.tab_PacketStormEXP.Visibility = Visibility.Visible;

                this.ListPacketStormEXP.AddHandler(System.Windows.Controls.Control.MouseDoubleClickEvent, new RoutedEventHandler(HandleDoubleClick));

                if (this.CheckForNewEntries(pacExp_vulns, "pacExp"))
                {
                    this.box.NotifyContent.Clear();

                    this.box.NotifyContent.Add(new NotifyObject("There have been new entries at Packet Storm Exploits", "Packet Storm Exploits"));

                    this.box.Notify();
                }
            }
            else
            {
                this.tab_PacketStormEXP.Visibility = Visibility.Collapsed;
            }

            this.LastUpdate.Content = "Last updated on: " + DateTime.Now.ToString();

            if (MySettings.getWatchList)
            {
                WaitCallback myCallback = new WaitCallback(bfunction);

                //add this to the thread pool / queue a task 

                ThreadPool.QueueUserWorkItem(myCallback);
            }
            
        }

        public void bfunction(object o)
        {
            this.checkWatchList();
            // do what ever the function is supposed to do. 
        }

        private delegate void UICallerDelegate1();

        private Collection<WatchListItem> wa_list;

        private void checkWatchList()
        {
            Watchlist_BL w = new Watchlist_BL();

            w.Os_vulns = vulns;

            if (MySettings.GetMilw0rm)
            {
                w.Mil_vulns = mil_vulns;
            }

            if (MySettings.getPacketVulns)
            {
                w.PackAdv_vulns = pacAdv_vulns;
            }

            if (MySettings.getPacketExpl)
            {
                w.PackExp_vulns = pacExp_vulns;
            }

            if (MySettings.getSecFocus)
            {
                w.Sec_vulns = sec_vulns;
            }

            wa_list = w.checkList();

            UICallerDelegate1 dlg = new UICallerDelegate1(setWatch);
            //BeginInvoke(dlg, null);
            //dlg.BeginInvoke(dlg, null);
            Dispatcher.BeginInvoke(DispatcherPriority.Normal, dlg);
        }

        private void setWatch()
        {
            if (wa_list.Count >= 1)
            {
                this.box.NotifyContent.Add(new NotifyObject("There has been vulnerabilites of your installed software", "Watchlist"));

                this.box.Notify();

                this.ListWatchList.DataContext = wa_list;
                this.tab_WatchList.Visibility = Visibility.Visible;
            }
        }

        private void HandleDoubleClick(object sender, EventArgs args)
        {
            String link = "";
            System.Windows.Controls.ListView view = (System.Windows.Controls.ListView)sender;

            if (view.SelectedItem is OSVDBVulns)
            {
                OSVDBVulns vuln = (OSVDBVulns)view.SelectedItem;

                link = vuln.Link;
            }
            else if (view.SelectedItem is Milw0rm)
            {
                Milw0rm vuln = (Milw0rm)view.SelectedItem;

                link = vuln.Link;
            }
            else if (view.SelectedItem is PacketStormADV)
            {
                PacketStormADV vuln = (PacketStormADV)view.SelectedItem;

                link = vuln.Link;
            }
            else if (view.SelectedItem is PacketStormEXP)
            {
                PacketStormEXP vuln = (PacketStormEXP)view.SelectedItem;

                link = vuln.Link;
            }

            if (link != "")
            {
                System.Diagnostics.Process.Start(link);
            }

        }

        private void OnTrayDoubleClick(object sender, EventArgs args)
        {
            this.Show();
            this.Activate();
            this.ShowInTaskbar = true;
            this.WindowState = WindowState.Normal;
        }

        private void doClose(object sender, EventArgs args)
        {
            this.user_shutdown = true;
            this.Close();
        }

        protected override void OnStateChanged(EventArgs e)
        {
            if (WindowState == WindowState.Minimized)
            {
                this.ShowInTaskbar = false;
            }

            base.OnStateChanged(e);           
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            if (!this.user_shutdown)
            {
                // Don't close, just Hide.
                e.Cancel = true;
                // Trying to hide
                System.Windows.Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, (DispatcherOperationCallback)delegate(object o)
                {
                    this.Hide();
                    return null;
                }, null);

                if (this.box.NotifyContent.Count != 0)
                {
                    this.box.NotifyContent.Clear();
                }

                if (MySettings.NotifyIfClosed)
                {
                    this.box.NotifyContent.Add(new NotifyObject("The application will still be open, but will be minimized to the traybar. If you don't want to read this message again, you can turn it off in the settings.", "Information"));

                    this.box.Notify();
                }
            }
            else
            {
                // Actually closing window.

                this.NotifyIcon.Visibility = Visibility.Collapsed;

                // Close the taskbar notifier too.
                if (this.box != null)
                    this.box.Close();
            }
        }

        private void mnuFileClose_Click(object sender, RoutedEventArgs e)
        {
            //this.user_shutdown = true;
            this.Close();
        }

        private void mnuExtrasInfo_Click(object sender, RoutedEventArgs e)
        {
            Stats stats = new Stats();
        }

        private void mnuExtrasSettings_Click(object sender, RoutedEventArgs e)
        {
            Setting set = new Setting(this);
            set.Show();
        }

        private bool CheckForNewEntries(Collection<AbstractVuln> list, String type)
        {
            bool isNew;
            switch (type)
            {
                case "OSVDB":
                    isNew = false;
                    if (this.MySettings.NewestOSVDB == null || firstStart)
                    {
                        this.MySettings.NewestOSVDB = (OSVDBVulns)list[0];
                        this.MySettings.Save();
                        firstStart = false;
                    }
                    else
                    {
                        OSVDBVulns vuln = (OSVDBVulns)list[0];

                        if (this.MySettings.NewestOSVDB.Date < vuln.Date)
                        {
                            isNew = true;
                        }
                    }
                    break;
                case "Milw0rm":
                    isNew = false;
                    if (this.MySettings.NewestMilw0rm == null || firstStartMil)
                    {
                        this.MySettings.NewestMilw0rm = (Milw0rm)list[0];
                        this.MySettings.Save();
                        firstStartMil = false;
                    }
                    else
                    {
                        Milw0rm vuln = (Milw0rm)list[0];

                       if (this.MySettings.NewestMilw0rm.Date < vuln.Date)
                        {
                            isNew = true;
                        }
                    }
                    break;
                case "SecFoc":
                    isNew = false;
                    if (this.MySettings.NewestSecFoc == null || firstStartSecFoc)
                    {
                        this.MySettings.NewestSecFoc = (SecFoc)list[0];
                        this.MySettings.Save();
                        firstStartSecFoc = false;
                    }
                    else
                    {
                        SecFoc vuln = (SecFoc)list[0];

                        if (this.MySettings.NewestSecFoc.Date < vuln.Date)
                        {
                            isNew = true;
                        }
                    }
                    break;
                case "pacAdv":
                    isNew = false;
                    if (this.MySettings.NewestPackAdv == null || firstStartPackAdv)
                    {
                        this.MySettings.NewestPackAdv = (PacketStormADV)list[0];
                        this.MySettings.Save();
                        firstStartPackAdv = false;
                    }
                    else
                    {
                        PacketStormADV vuln = (PacketStormADV)list[0];

                        if (this.MySettings.NewestPackAdv.Title == vuln.Title)
                        {
                            isNew = true;
                        }
                    }
                    break;
                case "pacExp":
                    isNew = false;
                    if (this.MySettings.NewestPackExp == null || firstStartPackExp)
                    {
                        this.MySettings.NewestPackExp = (PacketStormEXP)list[0];
                        this.MySettings.Save();
                        firstStartPackExp = false;
                    }
                    else
                    {
                        PacketStormEXP vuln = (PacketStormEXP)list[0];

                        if (this.MySettings.NewestPackExp.Title == vuln.Title)
                        {
                            isNew = true;
                        }
                    }
                    break;
                default:
                    isNew = false;
                    break;
            }

            return isNew;
        }

        private void mnuFileRefresh_Click(object sender, RoutedEventArgs e)
        {
            this.InitializeTimer();
            WaitCallback myCallback = new WaitCallback(afunction);

            //add this to the thread pool / queue a task 

            ThreadPool.QueueUserWorkItem(myCallback); 
        }

        private void mnuExtrasAbout_Click(object sender, RoutedEventArgs e)
        {
            AboutBox a = new AboutBox();
            a.Show();
        }
    }
}
